/*** 软件版权：XX有限公司
 　 * 修改记录：
 　 * 修改日期   修改人员     修改说明
 　 * =========  ===========  ====================================
 　 * 2020/10/12   WuZhen      新增
 　* =========  ===========  ====================================
 　 */
package com.example.springbootdemo.hander;


import com.example.springbootdemo.utils.BusinessException;
import com.example.springbootdemo.utils.WebResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolationException;
import java.nio.file.AccessDeniedException;
import java.text.ParseException;


/**
 * 功能说明：全局异常处理器
 * 　* 开发人员：WuZhen jujangai@163.com <br>
 * 开发时间：2020/10/12 <br>
 * 　功能描述：此处如果是返回统一响应结果的，则使用@RestControllerAdvice注解处理器类，如果需要返回页面的，则使用@ControllerAdvice，
 * 这里@ExceptionHandler指定处理的异常类型，一般如果项目的异常处理写的详细一点的话，还会添加认证异常、授权异常、参数校验异常 <br>
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {


    /**
     * 统一异常处理
     *
     * @param e 异常对象
     * @return 统一响应结果
     */
    @ResponseBody
    @ExceptionHandler({Exception.class, MethodArgumentNotValidException.class})
    @ResponseStatus(HttpStatus.OK)
    public WebResult handleException(Exception e) {
        if (e instanceof MethodArgumentNotValidException) {
            BindingResult result = ((MethodArgumentNotValidException) e).getBindingResult();
            if (result.hasErrors()) {
                FieldError error = result.getFieldError();
                return WebResult.fail(-1, "参数错误:[" + error.getField() + "]" + error.getDefaultMessage());
            }
        }

        if (e instanceof HttpRequestMethodNotSupportedException) {
            return WebResult.fail(-1, "请求方式错误:" + e.getMessage());
        }

        if (e instanceof HttpMessageConversionException) {
            log.warn("{}", e.getMessage());
            return WebResult.fail(-1, "请求错误");
        }
        /**参数校验错误  @NotnuLL之类的**/
        if (e instanceof ConstraintViolationException) {
            return WebResult.fail(-1, "参数错误:" + e.getMessage());
        }
        if (e instanceof MissingServletRequestParameterException) {
            log.warn(e.getMessage());
            return WebResult.fail(-1, "缺少必要参数");
        }
        if (e instanceof AccessDeniedException) {
            return WebResult.fail(-1, "禁止访问:" + e.getMessage());
        }
        if (e instanceof ParseException) {
            return WebResult.fail(-1, "坐标格式不正确:" + e.getMessage());
        }
        if (e instanceof NoHandlerFoundException) {
            return WebResult.fail(-1, "请求路径不存在");
        }
        if (e instanceof MethodArgumentTypeMismatchException) {
            return WebResult.fail(-1, "请求参数类型不符合规则");
        }
        /* ----------------------------sql------------------------------------- */
        if (e instanceof DuplicateKeyException) {
            return WebResult.fail(-1, "不允许重复添加");
        }

        if (e instanceof BusinessException) {
            BusinessException businessException = (BusinessException) e;
            return WebResult.fail(businessException.getCode(), e.getMessage());
        }
//        log.error("{}",e.getClass());
        log.error(" 系统异常 {}", e.getMessage(), e);

        return WebResult.fail(-1, "未知错误，请联系管理员！");
    }
}
